﻿
#include "zyLayout.h"

BlackMoonUI::zyLayout::zyLayout()
{
	SetMember(L"this", (LONG_PTR)this);
	m_obj->setWndProc(zyLayout_WndProc);
	m_obj->setDestroy(zyLayout_Destroy);
	init();
	SetMember(L"Type", zyLayoutType_Layout);//zyLayoutType_Layout
}
BlackMoonUI::zyLayout::~zyLayout()
{

}

void WINAPI BlackMoonUI::zyLayout::zyLayout_Destroy(zyObject* obj)
{
	// 释放 LayoutItems
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)obj->getPtrData(L"LayoutItems");
	if (pItems) {
        for (auto& item : *pItems) {
			if (item.pItemRect) {
				delete reinterpret_cast<RECT*>(item.pItemRect);
			}
			if (item.pRect) {
				delete reinterpret_cast<RECT*>(item.pRect);
			}
			if (item.pMargin) {
				delete reinterpret_cast<RECT*>(item.pMargin);
			}
		}
		delete pItems;
		obj->removePtrData(L"LayoutItems");
	}

	// 释放 pRect
	LONG_PTR pRect = (LONG_PTR)obj->getPtrData(L"pRect");
	if (pRect) {
		delete reinterpret_cast<RECT*>(pRect);
		obj->removePtrData(L"pRect");
	}
	zyBase::zyBase_Destroy(obj);
}
LRESULT WINAPI BlackMoonUI::zyLayout::zyLayout_WndProc(zyObject* obj, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL* bHandled){
	if (uMsg == zyLYM_SETSIZE) {
		zyLayout* zyl = (zyLayout*)obj->getPtrData(L"this");
		if(zyl == nullptr)
            return 0;
		int cx = (int)(INT_PTR)wParam;
		int cy = (int)(INT_PTR)lParam;
		RECT* pRect = zyl->zyLayout_SetSize(obj,cx, cy);
		wParam = cx;
		lParam = cy;
		return reinterpret_cast<LRESULT>(pRect);
	}
	return 0;
}
RECT* BlackMoonUI::zyLayout::zyLayout_SetSize(zyObject* obj, int& cx, int& cy) {
	RECT* pRect = (RECT*)(GetMember(L"pRect"));
	if (!pRect) return nullptr; // 如果 pRect 为空，直接返回

	RECT rc = *pRect; // 复制当前矩形
	// 获取最小宽度和高度
	int minWidth = (int)(INT_PTR)GetMember(L"minWidth");
	int minHeight = (int)(INT_PTR)GetMember(L"minHeight");

	// 如果最小宽度或高度未定义，则通过回调获取
	if (minWidth == -1 || minHeight == -1) {
		LRESULT minSize = (obj != nullptr) ? obj->callWndProc(0, zyLYM_GETMINSIZE, 0, 0, nullptr) : MAKELONG(100, 100);
		if (minWidth == -1) minWidth = LOWORD(minSize);
		if (minHeight == -1) minHeight = HIWORD(minSize);
	}

	// 确保 cx 和 cy 不小于最小宽度和高度
	cx = max(cx, minWidth);
	cy = max(cy, minHeight);
	/*if (cx < minWidth)
		cx = minWidth;
	if (cy < minHeight)
		cy = minHeight;*/
	// 更新矩形大小
	SetRect(pRect, rc.left, rc.top, rc.left + cx, rc.top + cy);
	return pRect;
}
void BlackMoonUI::zyLayout::init() {
	std::vector<zyLayoutItem>* pImtes = new std::vector<zyLayoutItem>();
	SetMember(L"LayoutItems", (LONG_PTR)pImtes);
	RECT *pRect = new RECT{ 0,0,10,10 };
	SetMember(L"pRect", (LONG_PTR)pRect);
	SetMember(L"minWidth", -1);
	SetMember(L"minHeight", -1);
}
void BlackMoonUI::zyLayout::布局() const {
	zyObject* Ptr = getObject();
	if (Ptr != nullptr) {
		BOOL bHand = false;
		Ptr->callWndProc(0, zyLYM_LAYOUT, 0, 0, &bHand);
	}
}
int BlackMoonUI::zyLayout::添加项目(zyBase& 参数_控件, 线性布局对齐 参数_对齐方式, RECT* 参数_边距, int 参数_最小宽度, int 参数_最小高度) {//成功返回索引，失败返回-1
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr) 
		return -1;
	zyLayoutItem Item = {0};
    Item.pObject = 参数_控件.getObject();
	Item.pObject->addRef();
    Item.align = (参数_对齐方式 == 线性布局对齐_错误) ? 线性布局对齐_左下 : 参数_对齐方式; // 默认对齐方式为7
    Item.pItemRect = new RECT{0, 0, 0, 0};
    Item.pRect = new RECT{ 0, 0, 0, 0 };
    Item.pMargin = new RECT{ 0, 0, 0, 0 };
	int type = (int)(INT_PTR)Item.pObject->getPtrData(L"Type");
	if (type == zyLayoutType_Layout) {
		RtlMoveMemory(Item.pRect, Item.pObject->getPtrData(L"pRect"), sizeof(RECT));
	}
	else {
		HWND hWnd = (HWND)Item.pObject->getPtrData(L"hWnd");
		GetClientRect(hWnd, Item.pRect);
	}

	// 设置边距
	*Item.pMargin = (参数_边距 != nullptr) ? *参数_边距 : RECT{ 5, 5, 5, 0 };
	// 设置最小宽度和高度
	RECT rc = *Item.pRect;
	Item.minWidth = (参数_最小宽度 == -1) ? (rc.right - rc.left) : 参数_最小宽度;
	Item.minHeight = (参数_最小高度 == -1) ? (rc.bottom - rc.top) : 参数_最小高度;

	// 添加项目到列表
	pItems->push_back(Item);
	int index = (int)pItems->size();

	// 更新布局的最小尺寸
	if (index != -1) {
		zyObject* Ptr = getObject();
		if (Ptr) {
			BOOL bHand = false;
			int minSize = (int)(INT_PTR)Ptr->callWndProc(0, zyLYM_GETMINSIZE, 0, 0, &bHand);
			RECT* pRect = (RECT*)(GetMember(L"pRect"));
			SetRect(pRect, pRect->left, pRect->top, pRect->left + LOWORD(minSize), pRect->top + HIWORD(minSize));
		}
	}
	return index;
}
int BlackMoonUI::zyLayout::插入项目(int 参数_索引, zyBase& 参数_控件, 线性布局对齐 参数_对齐方式, RECT* 参数_边距, int 参数_最小宽度, int 参数_最小高度) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return -1;
	int count = (int)pItems->size();
	if (参数_索引 < 0 || 参数_索引 > count) {
		参数_索引 = count;
	}
	zyLayoutItem Item = { 0 };
	Item.pObject = 参数_控件.getObject();
	Item.pObject->addRef();
	//IUnknown_AddRef(Item.pObject);
	int type = (int)(LONG_PTR)Item.pObject->getPtrData(L"Type");
	Item.align = (参数_对齐方式 == 线性布局对齐_错误) ? 线性布局对齐_左上 : 参数_对齐方式; // 默认对齐方式为7
	Item.pItemRect = new RECT{0,0,0,0};
	Item.pRect = new RECT{ 0,0,0,0 };
	Item.pMargin = new RECT{ 0,0,0,0 };
	if (type == zyLayoutType_Layout) {
		RtlMoveMemory(Item.pRect, Item.pObject->getPtrData(L"pRect"), sizeof(RECT));
	}
	else {
		HWND hWnd = (HWND)Item.pObject->getPtrData(L"hWnd");
		GetClientRect(hWnd, Item.pRect);
	}
	// 设置边距
	*Item.pMargin = (参数_边距 != nullptr) ? *参数_边距 : RECT{ 5, 5, 5, 0 };
	// 设置最小宽度和高度
	RECT rc = *Item.pRect;
	Item.minWidth = (参数_最小宽度 == -1) ? (rc.right - rc.left) : 参数_最小宽度;
	Item.minHeight = (参数_最小高度 == -1) ? (rc.bottom - rc.top) : 参数_最小高度;

	// 添加项目到列表
	pItems->insert(pItems->begin()+ 参数_索引, Item);
	int index = (int)pItems->size();
	//index = Array_Insert(pItems, 参数_索引, _取指针Struct(Item), LocalSize(Item));
	if (index != -1) {
		zyObject* Ptr = getObject();
		if (Ptr) {
			BOOL bHand = false;
			int minSize = (int)(INT_PTR)Ptr->callWndProc(0, zyLYM_GETMINSIZE, 0, 0, &bHand);
			RECT* pRect = (RECT*)(GetMember(L"pRect"));
			SetRect(pRect, pRect->left, pRect->top, pRect->left + LOWORD(minSize), pRect->top + HIWORD(minSize));
		}
	}
	return index;
}
bool BlackMoonUI::zyLayout::置项目对齐(int 参数_项目索引, 线性布局对齐 参数_布局属性) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return false;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return false;
	}
	// 设置对齐属性
	(*pItems)[参数_项目索引].align = 参数_布局属性;
	return true;
}
BlackMoonUI::线性布局对齐 BlackMoonUI::zyLayout::取项目对齐(int 参数_项目索引) {//看自己小键盘，0表示铺满
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return 线性布局对齐_错误;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return 线性布局对齐_错误;
	}
	return (*pItems)[参数_项目索引].align;
}
bool BlackMoonUI::zyLayout::置项目边距(int 参数_项目索引, RECT* 参数_边距) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return false;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return false;
	}
	SetRect((*pItems)[参数_项目索引].pMargin, 参数_边距->left, 参数_边距->top, 参数_边距->right, 参数_边距->bottom);
	return true;
}
RECT* BlackMoonUI::zyLayout::取项目边距(int 参数_项目索引) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return nullptr;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return nullptr;
	}
	return (*pItems)[参数_项目索引].pMargin;
}
bool BlackMoonUI::zyLayout::置项目控件(int 参数_项目索引, zyBase& 参数_控件) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return false;
	zyLayoutItem Item = (*pItems)[参数_项目索引];
	zyObject* pObject = 参数_控件.getObject();
	//IUnknown_AddRef(pObject);
	pObject->addRef();
	if (Item.pObject != 0) {
		Item.pObject->release();
	}
	Item.pObject = pObject;
	int type = (int)(LONG_PTR)Item.pObject->getPtrData(L"Type");
	if (type == zyLayoutType_Layout) {
		RtlMoveMemory(Item.pRect, Item.pObject->getPtrData(L"pRect"), 16);
	}
	else {
		HWND hWnd = (HWND)Item.pObject->getPtrData(L"hWnd");
		GetClientRect(hWnd, Item.pRect);
	}
	(*pItems)[参数_项目索引] = Item;
	zyObject* Ptr = getObject();
	if (Ptr) {
		BOOL bHand = false;
		int minSize = (int)(INT_PTR)Ptr->callWndProc(0, zyLYM_GETMINSIZE, 0, 0, &bHand);
		Ptr->callWndProc(0, zyLYM_SETSIZE, LOWORD(minSize), HIWORD(minSize), &bHand);
	}
	return true;
}
bool BlackMoonUI::zyLayout::取项目控件(int 参数_项目索引, zyBase& 参数_控件) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return false;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return false;
	}
	return 参数_控件.setObject((*pItems)[参数_项目索引].pObject);
}
SIZE BlackMoonUI::zyLayout::取项目最小尺寸(int 参数_项目索引) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return SIZE{0};
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return SIZE{ 0 };
	}
	SIZE size = { (*pItems)[参数_项目索引].minWidth ,(*pItems)[参数_项目索引].minHeight };
	return size;
}
bool BlackMoonUI::zyLayout::置项目最小尺寸(int 参数_项目索引, SIZE 参数_最小尺寸) {
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return false;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return false;
	}
	(*pItems)[参数_项目索引].minWidth = 参数_最小尺寸.cx;
	(*pItems)[参数_项目索引].minHeight = 参数_最小尺寸.cy;
	return true;
}
SIZE BlackMoonUI::zyLayout::取最小尺寸() {
	zyObject* Ptr = getObject();
	int minSize = 0;
	if (Ptr) {
		BOOL bHand = false;
		minSize = (int)(INT_PTR)Ptr->callWndProc(0, zyLYM_GETMINSIZE, 0, 0, &bHand);
	}
	SIZE size = { LOWORD(minSize), HIWORD(minSize) };
	return size;
}
void BlackMoonUI::zyLayout::置最小尺寸(int 参数_最小宽度, int 参数_最小高度) {//设置布局的最小尺寸
	SetMember(L"minWidth", 参数_最小宽度);
	SetMember(L"minHeight", 参数_最小高度);
}
void BlackMoonUI::zyLayout::置尺寸(int 参数_宽度, int 参数_高度) {//设置布局尺寸，不会小于最小尺寸
	zyObject* Ptr = getObject();
	if (Ptr) {
		BOOL bHand = false;
		Ptr->callWndProc(0, zyLYM_SETSIZE, 参数_宽度, 参数_高度, &bHand);
	}
}
RECT* BlackMoonUI::zyLayout::取矩形() {//获取布局的矩形范围
	RECT *pRect = (RECT*)GetMember(L"pRect");
	return pRect;
}
RECT* BlackMoonUI::zyLayout::取项目矩形(int 参数_项目索引) {//获取项目矩形范围，这个范围可能比控件大
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return nullptr;
	// 检查索引是否越界
	if (参数_项目索引 < 0 || 参数_项目索引 >= static_cast<int>(pItems->size())) {
		return nullptr;
	}
	return (*pItems)[参数_项目索引].pItemRect;
}
int  BlackMoonUI::zyLayout::取坐标项目(int 参数_横向坐标, int 参数_纵向坐标) {//成功返回项目索引，失败返回-1
	std::vector<zyLayoutItem>* pItems = (std::vector<zyLayoutItem>*)GetMember(L"LayoutItems");
	if (pItems == nullptr)
		return -1;
	for (size_t i = 0; i < pItems->size(); i++) {
		const zyLayoutItem item = (*pItems)[i];
		if (PtInRect(item.pItemRect, POINT{ 参数_横向坐标, 参数_纵向坐标 }) != 0) {
			return static_cast<int>(i);
		}
	}
	return -1;
}
RECT BlackMoonUI::zyLayout::zyGetAlignRectI(RECT srcRect, int align, int Width, int Height, int marginLeft, int marginTop, int marginRight, int marginBottom) {
	RECT rc = { 0 }; // 初始化目标矩形
	int left = 0;  // 目标矩形的左边界
	int top = 0;   // 目标矩形的上边界

	// 根据对齐方式计算目标矩形的位置
	switch (align) {
	case 7: // 左上对齐
		left = srcRect.left + marginLeft;
		top = srcRect.top + marginTop;
		break;
	case 8: // 上中对齐
		left = srcRect.left + (srcRect.right - srcRect.left + marginLeft - marginRight - Width) / 2;
		top = srcRect.top + marginTop;
		break;
	case 9: // 右上对齐
		left = srcRect.right - Width - marginRight;
		top = srcRect.top + marginTop;
		break;
	case 4: // 左中对齐
		left = srcRect.left + marginLeft;
		top = srcRect.top + (srcRect.bottom - srcRect.top + marginTop - marginBottom - Height) / 2;
		break;
	case 5: // 中心对齐
		left = srcRect.left + (srcRect.right - srcRect.left + marginLeft - marginRight - Width) / 2;
		top = srcRect.top + (srcRect.bottom - srcRect.top + marginTop - marginBottom - Height) / 2;
		break;
	case 6: // 右中对齐
		left = srcRect.right - Width - marginRight;
		top = srcRect.top + (srcRect.bottom - srcRect.top + marginTop - marginBottom - Height) / 2;
		break;
	case 1: // 左下对齐
		left = srcRect.left + marginLeft;
		top = srcRect.bottom - Height - marginBottom;
		break;
	case 2: // 下中对齐
		left = srcRect.left + (srcRect.right - srcRect.left + marginLeft - marginRight - Width) / 2;
		top = srcRect.bottom - Height - marginBottom;
		break;
	case 3: // 右下对齐
		left = srcRect.right - Width - marginRight;
		top = srcRect.bottom - Height - marginBottom;
		break;
	case 0: // 拉伸对齐（填充整个区域）
		SetRect(&rc, srcRect.left + marginLeft, srcRect.top + marginTop, srcRect.right - marginRight, srcRect.bottom - marginBottom);
		return rc; // 直接返回结果
	default: // 默认对齐方式（无对齐）
		SetRect(&rc, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom);
		return rc; // 直接返回结果
	}

	// 设置目标矩形的右边界和下边界
	SetRect(&rc, left, top, left + Width, top + Height);

	// 确保目标矩形不超出源矩形的边界（考虑边距）
	if (rc.left < srcRect.left + marginLeft) {
		rc.left = srcRect.left + marginLeft;
	}
	if (rc.top < srcRect.top + marginTop) {
		rc.top = srcRect.top + marginTop;
	}

	return rc; // 返回计算后的矩形
}